﻿namespace ChinaUnicom.Web
{
    using System;
    using System.Linq;
    using System.Net;
    using System.Text;
    using ChinaUnicom.Exceptions;

    class WebRequestOperation : IOperation
    {
        // Windows Phone OS 7.5 IE 9.0
        const string UserAgent = "Mozilla/5.0 (compatible; MSIE 9.0; Windows Phone OS 7.5; Trident/5.0; IEMobile/9.0; SAMSUNG; SGH-i917)";

        const string Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
        const string ContentType = "application/x-www-form-urlencoded";
        const string KeepAlive = "keep-alive";

        const string BaseUrl = "http://mob.10010.com/";

        const string LoginUrl = "http://mob.10010.com/mini/login.do?type=local";
        const string LoginPostParameters = "mobile={0}&password={1}&imgCode={2}";

        const string AutoLoginUrl = "http://mob.10010.com/mini/operationservice/beforeHistoryBusinessBL.do";

        const string LogoutUrl = "http://mob.10010.com/mini/loginOut.do";
        const string UserInfoUrl = "http://mob.10010.com/mini/operationservice/getUserinfo.do";
        const string RealFeeUrl = "http://mob.10010.com/mini/query/queryRealFee.do";
        const string PackageFlowLeftUrl = "http://mob.10010.com/mini/operationservice/queryOcsPackageFlowLeft.do";
        const string ImageStreamParameters = "http://mob.10010.com/mini/sinova.gif?width=72&height=21&r={0}";

        const string SessionUrlTemplate = "http://mob.10010.com/mini/secureLogin.do?secure={0}";

        Uri SessionUri;
        CookieContainer cookies;

        public WebRequestOperation()
        {
            SessionUri = null;
            cookies = new CookieContainer();
            if (Authentication.Current.Authorized)
            {
                cookies.Add(new Uri(BaseUrl), Authentication.Current.Cookie);
            }
        }

        void GetSecure(Action callback)
        {
            // secureLogin\.do\?secure=[\s|\d]+
            WebRequestHelper.Execute(CreateRequest(new Uri(BaseUrl)), s =>
            {
                System.Text.RegularExpressions.Regex r = new System.Text.RegularExpressions.Regex(@"secureLogin\.do\?secure=\w+");
                var sourceMatch = r.Match(s.Result);
                if (sourceMatch.Success)
                {
                    SessionUri = new Uri(string.Format(SessionUrlTemplate, sourceMatch.Value.Substring("secureLogin.do?secure=".Length)));
                }

                if (callback != null) { callback(); }
            });
        }

        public void CreateSession(Action<HttpStatus> callback)
        {
            if (SessionUri == null)
            {
                GetSecure(() => WebRequestHelper.Execute(CreateRequest(SessionUri), callback));
            }
            else
            {
                WebRequestHelper.Execute(CreateRequest(SessionUri), callback);
            }
        }

        public void Login(string mobile, string password, string imgcode, Action<HttpStatus> callback)
        {
            HttpWebRequest request = CreateRequest(new Uri(LoginUrl), HttpMethod.POST);

            // post data.
            request.BeginGetRequestStream(s =>
            {
                var stream = request.EndGetRequestStream(s);
                var buffer = Encoding.UTF8.GetBytes(string.Format(LoginPostParameters, mobile, password, imgcode));
                stream.Write(buffer, 0, buffer.Length);
                stream.Close();

                WebRequestHelper.Execute(request, x =>
                {
                    var cookie = cookies.GetCookies(SessionUri).Cast<Cookie>().FirstOrDefault(c => c.Name == Authentication.Key);
                    if (cookie != null)
                    {
                        Authentication.Current.Register(cookie.Value);
                    }

                    if (callback != null)
                    {
                        if (cookie == null)
                        {
                            x.Exception = new UnicomException(Factory.Parser.Failed(x.Result));
                            x.StatusCode = HttpStatusCode.Unauthorized;
                        }

                        callback(x);
                    }
                });

            }, null);
        }

        public void Logout()
        {
            // clear cookies
            this.cookies = new CookieContainer();
        }

        public void RequestUserInfo(Action<HttpStatus> callback)
        {
            WebRequestHelper.Execute(CreateRequest(new Uri(UserInfoUrl)), callback);
        }

        public void RequestFeeInfo(Action<HttpStatus> callback)
        {
            WebRequestHelper.Execute(CreateRequest(new Uri(RealFeeUrl)), callback);
        }

        public void RequestPackageInfo(Action<HttpStatus> callback)
        {
            WebRequestHelper.Execute(CreateRequest(new Uri(PackageFlowLeftUrl)), callback);
        }

        public void RequestCodeImage(Action<HttpStatus> callback)
        {
            int r = new Random((int)DateTime.Now.Ticks).Next();
            WebRequestHelper.Execute(CreateRequest(new Uri(string.Format(ImageStreamParameters, r))), callback);
        }

        public void AutoLogin(Action<HttpStatus> callback)
        {
            WebRequestHelper.Execute(CreateRequest(new Uri(AutoLoginUrl)), callback);
        }

        HttpWebRequest CreateRequest(Uri uri, HttpMethod method = HttpMethod.GET)
        {
            // Create a HttpWebrequest object to the desired URL.
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
            request.Method = "GET";

            if (method == HttpMethod.POST)
            {
                request.Method = "POST";
                request.ContentType = ContentType;
            }

            request.UserAgent = UserAgent;
            request.Accept = Accept;
            request.Headers["Connection"] = KeepAlive;
            request.CookieContainer = cookies;

            return request;
        }
    }
}
